Pragma Directives of lcc-win32

Packing directives. These directives tell the compiler how to pack the structure members.

This directive can have two forms:

#pragma pack(n)

where n is 1,2,4,8, or 16. This will align the members of a structure at 1 (i.e., no packing) at 2, 4, 8, or 16 bytes.

You can also use:

#pragma pack(push,n)

This will save the current value of the packing constant, and set it to n, which should be an integer as explained above. After some code, this allows you  to use:

#pragma pack(pop)

to restore the original value again.

Example:

The most common use is at the beginning of an include file to set the value to a certain amount, and to restore it at the end of the file.

#pragma pack(push,1)

.....

#pragma pack(pop)

EOF

Include directives. The pragma

#pragma once

will ensure that the current file will be read only once by the compiler. Any further directives for #including the same file will have no affect.

Optimization directives. This allows you to set the optimization flag on or off at certain functions.

#pragma optimize(n)

where n will be either zero (no optimizations) or one (optimizations).

Switch generation control. The pragma

#pragma density(push,0.0)

will trigger the compiler to generate a table of all possible switch values between the lowest and the highest case statements found, making a tradeoff that penalizes space for speed. This can of course overflow if you have:

     switch(i) {

     case -10000000:

          ...

     case 10000000:

          ...

     }

In this example, the generated table would have 20 million positions, which may not be a good idea.

On the contrary, in other cases where the numbers are densely packed, this can be an ideal optimization.

Including libraries for the link command

#pragma lib "mylib.lib"

#pragma lib <mylib.lib>

This pragmas allow you to automatically include a library that is associated with a header file. Paths enclosed in double quotes will be understood as absolute paths, paths enclosed in <> will be searched in the standard library paths (normally \lcc\lib).

 

 

Runtime Organization

A stack frame is an area of storage associated with the activation of a function. A stack frame that is allocated as a function is entered, and it is deallocated when the function exits. Automatic (auto) variables are compiler-generated temporaries that are located in the stack frame. It is organized as follows:

 

second parameter

ESP+8

first parameter

ESP+4

caller’s return address

ESP+0

saved frame pointer

ESP-4

local variables and temporaries

ESP-8 ESP -n

saved registers (if any)

 

 

Usually, it is the EBP register that points to the stack frame. This register is used to address all local variables and arguments. When possible, and when the user has specified the –O (optimization) flag, lcc will not build a full stack frame, but just a minimal one, consisting only of the saved return address and the registers used by the procedure.

 

Saved Registers, Prolog and Epilog Sequences

Lcc-win32 always saves the registers EBX, EBP, ESI and EDI. Under no circumstances when writing assembly modules should the values stored in these registers be lost.

A prolog is the code executed immediately upon a function entry, i.e., the code that builds the stack frame for the function and saves the registers that the function will use. An epilog is the code executed to deallocate the stack frame, and restore the saved values of the registers.

The prolog sequence of lcc-win32 is:

            push     %ebp               ; save the frame pointer

            movl     %esp,%ebp      ; move the stack pointer to the frame pointer

            subl      <n>,%esp        ; allocate space in the stack for the function’s variables

            push     %esi                 ; save registers

            push     %edi

            push     %ebx

Symmetrically, the epilog sequence looks like this :

       pop      %ebx               ; restore the saved registers

       pop      %edi

       pop      %esi

       movl     %ebp,%esp      ; restore the stack

       popl     %ebp               ; restore the old frame pointer

       ret                                ;return to caller. Caller responsible for cleaning the stack.

Registry Use of lcc-win32

Lcc creates the following key in the registry:

HKEY_CURRENT_USER\SOFTWARE\lcc

This key contains the following subkeys:

1.   lcc\General              General type of information

2.   lcc\Compiler                        Compiler specific information

3.   lcc\Wedit                  For the IDE

4.   lcc\lcclnk                   For the linker

5.   lcc\weditres             For the resource editor

6.   lcc\db                                    Database extension

 

Following is a description of all keys used by lcc-win32. The prefix

HKEY_CURRENT_USER\Software\lcc

is assumed in all of them.

 

Key name

Contents and description

SmallEiffel

Path to the SmallEiffel compiler

Version

Version number, for example “2.7”

compiler\includepath

Path to the directory included

lcclnk\libpath

Path to the libraries

Wedit

Project management

All the keys following this will have the implicit path:

HKEY_CURRENT_USER\Software\lcc\Wedit

Accel

Number of user-defined accelerators

Acceln

Contents for the nth accelerator

BackgroundColor

RGB for the current background color

CommentColor

RGB for comment color

CurrentDir

Current working directory

Predefined Preprocessor Symbols

Lcc-win32 defines the following symbols:[1]

Symbol

Meaning

__STDC__

Defined to 1. This identifies lcc-win32 as an ANSI C compiler.

__DATE__

Contains the current compilation date in the format: MMM DD YYY as a character string.

__TIME__

Contains the current time as a character string in the format: HH:MM:SS Note that this “timer” does not change, even if the compilation takes a long time.

__FILE__

Contains the name of the current file without any path component as a character string.

__func__

This symbol will be expanded by the compiler to a character string containing the name of the current function being compiled, or the character string “<none>”if no function is currently being defined.[2]

__LINE__

This symbol will be expanded to an integer containing the current line number in the source file. Note that this line number can be changed to an arbitrary value with the # line directive.

__LCC__

Allows you to conditionally compile source for the lcc compiler.

__LCCOPTIMLEVEL

If optimization is on, i.e., the –O option was given in the command line or if the #pragma optimize was parsed, this preprocessor variable will have the value one. If no optimizations are active, its value is zero.

__LCCDEBUGLEVEL

If the compiler is called with the –g<n> option (debug level n) the value of LCCDEBUGLEVEL is n. If there is no –g in the compiler’s command line, then its value is zero.

RC_INVOKED

Defined by the resource compiler when active.

WINVER

Contains a two-byte number with the major version number of windows in the high byte, and the minor version number in the low byte. This value is determined at compile time. Note that this predefined symbol CAN be changed with the #undef directive.

WIN32

_WIN32

Defined to 1. Note that contrary to other predefined symbols, this symbol can be undefined with the #undef directive.

__int64

Defined as the long long integer type for compatibility with the Microsoft compiler.

__cdecl

__inline

_cdecl

_huge

Defined to the empty string for compatibility reasons.

Predefined Compiler Symbols

 

Symbol

Meaning

_asm(“ “);

In-line assembly instruction(s).

_stdcall

Call convention declaring a function that cleans up the stack before executing the return statement.

_try

Introduces a try block in the Win32 structured exception handling.

_except

Finishes a structured try block.

__declspec

Declare special. Its arguments can be:

__declspec(dllimport)

meaning the symbol following this declaration is imported from a foreign DLL, or:

__declspec(dllexport)

meaning this symbol should be exported from the DLL being compiled.

 

 



[1]  Note that none of this identifiers can be undefined with the #undef macro directive.

[2] The standard gives the following definition for this:

“The identifier _ _func_ _ shall be implicitly declared by the translator as if, immediately following the opening brace of each function definition, the declaration static const char _ _func_ _[]="function-name"; appeared, where function-name is the name of the lexically-enclosing function.”.

WG14/N843 ANSI standard page 45. Note that the behavior of lcc-win32 is more lenient: the symbol still has a valid value outside a function.